package sys

/*******************************************************************************
Copyright:cloud
Author:cloudapex@126.com
Version:1.0
Date:2020-06-12
Description: 系统.用户组
*******************************************************************************/
import (
	"context"
	"permis/api/api"
	"permis/api/cache"
	"permis/model"

	gpc "gitee.com/cloudapex/protos/comm/pb"
	gpb "gitee.com/cloudapex/protos/permis/pb"

	"gitee.com/cloudapex/ulern/util"
)

/*
 * 描述: 组织列表
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupList(ctx context.Context, req *gpb.GroupListReq) (*gpb.GroupListRes, error) {
	items, err := (&model.Group{
		CoId:  req.CoId,
		Name:  req.Name,
		State: req.State,
	}).Find()
	if err != nil {
		return nil, api.DBError("", err)
	}

	res := &gpb.GroupListRes{}
	if err := util.Convert(&res.List, items); err != nil {
		return nil, api.ConvertError("", err)
	}
	return res, nil
}

/*
 * 描述: 组织树表
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupTree(ctx context.Context, req *gpc.IdRequest) (*gpb.GroupTreeRes, error) {
	items, err := (&model.Group{CoId: req.Id}).FindTree()
	if err != nil {
		return nil, api.DBError("", err)
	}
	res := &gpb.GroupTreeRes{}
	if err := util.Convert(&res.List, items); err != nil {
		return nil, api.ConvertError("", err)
	}
	return res, nil
}

/*
 * 描述: 新增组织
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupAdd(ctx context.Context, req *gpb.GroupAddReq) (*gpc.IdResponse, error) {
	p := &model.Group{Id: req.ParentId}
	if req.ParentId != 0 {
		if has, err := p.Load(); !has || err != nil {
			return nil, api.DBError("上级用户组不存在", err)
		}
		if p.CoId != req.CoId {
			return nil, api.Error(api.ECode_ParamsErr, "所属公司不一致", nil)
		}
	}

	m := model.Group{
		CoId:     req.CoId,
		ParentId: req.ParentId,
		NodePath: model.NodePath(p.NodePath, p.Id),
		Icon:     req.Icon,
		Name:     req.Name,
		Tntyp:    model.ETreeNode_Leaf,
		Order:    req.Order,
		State:    req.State,
	}
	if _, err := m.Create(); err != nil {
		return nil, api.DBError("创建用户组失败", err)
	}

	// 把父节点的角色关联下沉
	if p.Tntyp == model.ETreeNode_Leaf {
		if _, err := (&model.Group{Tntyp: model.ETreeNode_Base}).Update(p.Id); err != nil {
			return nil, api.DBError("更新父级用户组类型失败", err)
		}
		if _, err := (&model.GroupRole{}).UpdGroup(p.Id, m.Id); err != nil {
			return nil, api.DBError("更新父级用户组成员失败", err)
		}
	}
	return &gpc.IdResponse{Id: m.Id}, nil
}

/*
 * 描述: 编辑组织
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupUpd(ctx context.Context, req *gpb.GroupUpdReq) (*gpc.UnResponse, error) {
	m := model.Group{
		Id:    req.Id,
		Icon:  req.Icon,
		Name:  req.Name,
		Order: req.Order,
		State: req.State,
	}
	// 更新记录, 允许后面的几个字段被重置为默认值
	if _, err := m.Update(req.Id, "icon", "order"); err != nil {
		return nil, api.DBError("", err)
	}
	return &gpc.UnResponse{}, nil
}

/*
 * 描述: 删除组织
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupDel(ctx context.Context, req *gpc.IdRequest) (*gpc.UnResponse, error) {
	// for self
	eff, err := (&model.Group{}).Delete(req.Id)
	if err != nil {
		return nil, api.DBError("", err)
	}
	if eff == 0 {
		return nil, api.FoundError("此用户组不存在", err)
	}

	// 影响的哪些用户
	uIds, err := (&model.UserGroup{GroupId: req.Id}).FindIds()
	if err != nil {
		this.Error("UserChoose.FindIds err:%v", err)
	}

	// for user cache
	util.Goroutine("HandUserRoles", func() { // 更新用户角色缓存
		if err := cache.HandUserRoles(uIds, false); err != nil {
			this.Error("UserChoose.HandUserRoles err:%v", err)
		}
	})

	// for user group
	if _, err := (&model.UserGroup{}).Delete(0, req.Id); err != nil {
		return nil, api.DBError("用户组织操作失败", err)
	}

	// for group role
	if _, err := (&model.GroupRole{}).Delete(req.Id, 0); err != nil {
		return nil, api.DBError("用户组角色操作失败", err)
	}
	return &gpc.UnResponse{}, nil
}

/*
 * 描述: 获取组织角色Ids
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupChoice(ctx context.Context, req *gpc.IdRequest) (*gpb.GroupChoiceRes, error) {
	ids, err := (&model.GroupRole{GroupId: req.Id}).FindIds()
	if err != nil {
		return nil, api.DBError("", err)
	}
	return &gpb.GroupChoiceRes{Ids: ids}, nil
}

/*
 * 描述: 修改组织角色Ids
 * 方法: Simple
 *********************************************************************/
func (this *Server) GroupChoose(ctx context.Context, req *gpb.GroupChooseReq) (*gpc.UnResponse, error) {
	mGroup := model.Group{Id: req.GId}
	if has, err := mGroup.Load(); !has || err != nil {
		return nil, api.DBError("此用户组不存在", err)
	}

	if mGroup.Tntyp != model.ETreeNode_Leaf {
		return nil, api.Error(api.ECode_Logic, "只有叶子节点组可以绑定角色")
	}

	if vry, err := (&model.Role{}).VerifyIds(req.RIds); !vry || err != nil {
		return nil, api.DBError("角色验证失败", err)
	}

	mGR := model.GroupRole{}
	if _, err := mGR.Delete(req.GId, 0); err != nil {
		return nil, api.DBError("用户组角色操作失败", err)
	}

	if err := mGR.Insert(req.GId, req.RIds); err != nil {
		return nil, api.DBError("用户组角色更新失败", err)
	}

	util.Goroutine("HandUserRoles", func() { // 更新用户角色缓存
		// 影响的哪些用户
		uIds, err := (&model.UserGroup{GroupId: req.GId}).FindIds()
		if err != nil {
			this.Error("UserChoose.FindIds err:%v", err)
		}

		if err := cache.HandUserRoles(uIds, false); err != nil {
			this.Error("UserChoose.HandUserRoles err:%v", err)
		}
	})

	return &gpc.UnResponse{}, nil
}
